package Vshift

import chisel3._
import chisel3.util._
import VShiftInstr._

class SrcData extends Bundle{
  val oprand1_low = UInt(WIDTH64.W)
  val oprand1_hig = UInt(WIDTH64.W)
  val oprand2_low = UInt(WIDTH64.W)
  val oprand2_hig = UInt(WIDTH64.W)
}

class DstData extends Bundle{
  val LongResult1_128 = Vec(1, UInt(128.W))
  val LongResult2_64 = Vec(2, UInt(64.W))
  val LongResult4_32 = Vec(4, UInt(32.W))
  val LongResult8_16 = Vec(8, UInt(16.W))

  val result1_64 = Vec(1, UInt(64.W))
  val result2_32 = Vec(2, UInt(32.W))
  val result4_16 = Vec(4, UInt(16.W))
  val result8_8  = Vec(8, UInt(8.W))
}

class VShiftDataReady(sec: Int = 1) extends Module {
  val io = IO(new Bundle() {
//    val inst = Input(UInt(WIDTH32.W))
    val srcData = Input(new SrcData())
    val vcon = Input(new Vcon())
    val velem = Input(new Velem())
    val vdec = Input(new Vdec())
    val dstValue = Input(UInt(WIDTH64.W))

    val sat = Output(UInt(1.W))
    val dstData = Output(new DstData())
  })

  io.sat := 0.U

  //----------------------------------------------------------------------
  //src_low src_high generate

  val (src1,src2) =
    if (sec==1) (io.srcData.oprand1_low(63,0),io.srcData.oprand2_low(63,0))
    else (io.srcData.oprand1_hig(63,0),io.srcData.oprand2_hig(63,0))

  //----------------------------------------------------------------------
  //operat1 generate

  val src1elem8 = Elem(src1, 8, 8)
  val src1elem4 = Elem(src1, 4, 16)
  val src1elem2 = Elem(src1, 2, 32)
  val src1elem1 = Elem(src1, 1, 64)

  val src2elem8 = Elem(src2, 8, 8)
  val src2elem4 = Elem(src2, 4, 16)
  val src2elem2 = Elem(src2, 2, 32)
  val src2elem1 = Elem(src2, 1, 64)

  val dstElem8 = Elem(io.dstValue, 8, 8)
  val dstElem4 = Elem(io.dstValue, 4, 16)
  val dstElem2 = Elem(io.dstValue, 2, 32)
  val dstElem1 = Elem(io.dstValue, 1, 64)

  val src1elem1_N = Elem(Cat(io.srcData.oprand1_hig,io.srcData.oprand1_low), 1, 128)
  val src1elem2_N = Elem(Cat(io.srcData.oprand1_hig,io.srcData.oprand1_low), 2, 64)
  val src1elem4_N = Elem(Cat(io.srcData.oprand1_hig,io.srcData.oprand1_low), 4, 32)
  val src1elem8_N = Elem(Cat(io.srcData.oprand1_hig,io.srcData.oprand1_low), 8, 16)

  val result8 = WireInit(0.U.asTypeOf(Vec(8, UInt(8.W))))
  val result4 = WireInit(0.U.asTypeOf(Vec(4, UInt(16.W))))
  val result2 = WireInit(0.U.asTypeOf(Vec(2, UInt(32.W))))
  val result1 = WireInit(0.U.asTypeOf(Vec(1, UInt(64.W))))

  val result1_long = WireInit(0.U.asTypeOf(Vec(1, UInt(128.W))))
  val result2_long = WireInit(0.U.asTypeOf(Vec(2, UInt(64.W))))
  val result4_long = WireInit(0.U.asTypeOf(Vec(4, UInt(32.W))))
  val result8_long = WireInit(0.U.asTypeOf(Vec(8, UInt(16.W))))

  io.dstData.result1_64 := result1
  io.dstData.result2_32 := result2
  io.dstData.result4_16 := result4
  io.dstData.result8_8  := result8

  io.dstData.LongResult1_128 := result1_long
  io.dstData.LongResult2_64  := result2_long
  io.dstData.LongResult4_32  := result4_long
  io.dstData.LongResult8_16  := result8_long

  val shiftResult8 = WireInit(0.U.asTypeOf(Vec(8, UInt(136.W))))   //8+128 = 136
  val shiftResult4 = WireInit(0.U.asTypeOf(Vec(4, UInt(144.W))))   //16+128 = 144
  val shiftResult2 = WireInit(0.U.asTypeOf(Vec(2, UInt(160.W))))   //32+128 = 160
  val shiftResult1 = WireInit(0.U.asTypeOf(Vec(1, UInt(192.W))))   //128+64 = 192

  // no limit instruction
  val result1_32 = WireInit(0.U.asTypeOf(Vec(1, UInt(32.W))))
  val result1_16 = WireInit(0.U.asTypeOf(Vec(1, UInt(16.W))))
  val result1_8 = WireInit(0.U.asTypeOf(Vec(1, UInt(8.W))))
  val shiftResult1_32 = WireInit(0.U.asTypeOf(Vec(1, UInt(160.W))))   //128+64 = 192
  val shiftResult1_16 = WireInit(0.U.asTypeOf(Vec(1, UInt(144.W))))   //128+64 = 192
  val shiftResult1_8 = WireInit(0.U.asTypeOf(Vec(1, UInt(136.W))))   //128+64 = 192

  val shiftMask1 = WireInit(0.U.asTypeOf(Vec(1, UInt(64.W))))
  val shiftMask2 = WireInit(0.U.asTypeOf(Vec(2, UInt(32.W))))
  val shiftMask4 = WireInit(0.U.asTypeOf(Vec(4, UInt(16.W))))
  val shiftMask8 = WireInit(0.U.asTypeOf(Vec(8, UInt(8.W))))


  //---------------------------------------------------------------------=
  //operat1 generate

  val immh = Wire(UInt(4.W))
  val immb = Wire(UInt(3.W))
  val size = Wire(UInt(2.W))

  immh := io.vdec.immh
  immb := io.vdec.immb
  size := io.vdec.size

  val control_rsnlia = Wire(UInt(6.W))
  control_rsnlia := Cat(io.vcon.round, io.vcon.sat, io.vcon.narrow, io.vcon.long, io.vcon.insert, io.vcon.accum)

  //---------------------------------------------------------------------=
  //shiftvalu and round generate

  val shiftvalu = WireInit(0.U.asTypeOf(Vec(8, UInt(8.W))))
  val roundvalu = WireInit(0.U.asTypeOf(Vec(8, UInt(4.W))))
  val shiftReverse = WireInit(0.U.asTypeOf(Vec(8, UInt(1.W))))


  switch(io.velem.esize) {
    is(64.U) { //64、32、16、8
      switch(io.velem.shiftvaluVcon) {
        is(0.U){
          shiftvalu(0) := (Cat(immh, immb) - io.velem.esize)
          roundvalu(0) := 1.U << (-shiftvalu(0) - 1.U)
          shiftReverse(0) := 0.U
        }
        is(1.U){
          shiftvalu(0) := (io.velem.esize << 1.U).asUInt - Cat(immh, immb)
          roundvalu(0) := 1.U << (-shiftvalu(0) - 1.U)
          shiftReverse(0) := 0.U
        }
        is(2.U){
          when(src2elem1(0)(7) === 0.U) {
            shiftvalu(0) := src2elem1(0)(7, 0)
            shiftReverse(0) := 0.U
            roundvalu(0) := 1.U << (-shiftvalu(0) - 1.U)
          }.otherwise {
            shiftvalu(0) := -src2elem1(0)(7, 0)
            shiftReverse(0) := 1.U
            roundvalu(0) := 1.U << (shiftvalu(0) - 1.U)
          }
        }
        is(3.U){
          shiftvalu(0) := io.velem.esize
          roundvalu(0) := 1.U << (-shiftvalu(0) - 1.U)
          shiftReverse(0) := src2elem1(0)(7)
        }
      }
    }
    is(32.U) { //2 x 32
      for (i <- 0 to 1) {
        switch(io.velem.shiftvaluVcon) {
          is(0.U) {
            shiftvalu(i) := (Cat(immh, immb) - io.velem.esize)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(1.U) {
            shiftvalu(i) := (io.velem.esize << 1.U).asUInt - Cat(immh, immb)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(2.U) {
            roundvalu(i) := (1.U << (-src2elem2(i)(7,0)) - 1.U)
            when(src2elem2(i)(7) === 0.U) {
              shiftvalu(i) := src2elem2(i)(7, 0)
              shiftReverse(i) := 0.U
            }.otherwise {
              shiftvalu(i) := -src2elem2(i)(7, 0)
              shiftReverse(i) := 1.U
            }
          }
          is(3.U) {
            shiftvalu(i) := io.velem.esize
            roundvalu(i) := 1.U << -shiftvalu(i) - 1.U
            shiftReverse(i) := src2elem2(i)(7)
          }
        }
      }
    }
    is(16.U) { //4 x 16
      for (i <- 0 to 3) {
        switch(io.velem.shiftvaluVcon) {
          is(0.U) {
            shiftvalu(i) := (Cat(immh, immb) - io.velem.esize)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(1.U) {
            shiftvalu(i) := (io.velem.esize << 1.U).asUInt - Cat(immh, immb)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(2.U) {
            roundvalu(i) := (1.U << (-src2elem4(i)(7,0)) - 1.U)
            when(src2elem4(i)(7) === 0.U) {
              shiftvalu(i) := src2elem4(i)(7, 0)
              shiftReverse(i) := 0.U
            }.otherwise {
              shiftvalu(i) := -src2elem4(i)(7, 0)
              shiftReverse(i) := 1.U
            }
          }
          is(3.U) {
            shiftvalu(i) := io.velem.esize
            roundvalu(i) := 1.U << -shiftvalu(i) - 1.U
            shiftReverse(i) := src2elem4(i)(7)
          }
        }
      }
    }
    is(8.U) { //8 x 8
      for (i <- 0 to 7) {
        switch(io.velem.shiftvaluVcon) {
          is(0.U) {
            shiftvalu(i) := (Cat(immh, immb) - io.velem.esize)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(1.U) {
            shiftvalu(i) := (io.velem.esize << 1.U).asUInt - Cat(immh, immb)
            roundvalu(i) := 1.U << (-shiftvalu(i) - 1.U)
            shiftReverse(i) := 0.U
          }
          is(2.U) {
            roundvalu(i) := (1.U << (-src2elem8(i)(7,0)) - 1.U)
            when(src2elem8(i)(7) === 0.U) {
              shiftvalu(i) := src2elem8(i)(7, 0)
              shiftReverse(i) := 0.U
            }.otherwise {
              shiftvalu(i) := -src2elem8(i)(7, 0)
              shiftReverse(i) := 1.U
            }
          }
          is(3.U) {
            shiftvalu(i) := io.velem.esize
            roundvalu(i) := 1.U << -shiftvalu(i) - 1.U
            shiftReverse(i) := src2elem8(i)(7)
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //shiftResult operation                                 Num=1 esize=64//

  when(io.velem.esize === 64.U) {
    when((io.vcon.shiftLr ^ shiftReverse(0)) === 0.U){
      when(io.vcon.round === 1.U){
        shiftResult1(0) := (Cat(Fill(128,src1elem1(0)(63)),src1elem1(0)) + roundvalu(0)) << shiftvalu(0)  //left+round
      }.otherwise{
        shiftResult1(0) := Cat(Fill(128,src1elem1(0)(63)),src1elem1(0)) << shiftvalu(0)                   //left
      }
    }.otherwise{                                            //(right）
      when(io.vcon.srcSign === 1.U){
        when(io.vcon.narrow === 1.U){
          when(io.vcon.round === 1.U){                      //right+srcsign+narrow+round
            shiftResult1(0) := ((Cat(Fill(64,src1elem1_N(0)(127)),src1elem1_N(0)) + roundvalu(0)).asSInt >> shiftvalu(0)).asUInt
          }.otherwise{                                      //right+srcsign+narrow
            shiftResult1(0) := (Cat(Fill(64,src1elem1_N(0)(127)),src1elem1_N(0)).asSInt >> shiftvalu(0)).asUInt
          }
        }.otherwise{
          when(io.vcon.round === 1.U){                      //right+srcsign+round
            shiftResult1(0) := ((Cat(Fill(128,src1elem1(0)(63)),src1elem1(0)) + roundvalu(0)).asSInt >> shiftvalu(0)).asUInt
          }.otherwise{                                      //right+srcsign
            shiftResult1(0) := (Cat(Fill(128,src1elem1(0)(63)),src1elem1(0)).asSInt >> shiftvalu(0)).asUInt
          }
        }
      }.otherwise{                                         //(no srcsign)
        when(io.vcon.narrow === 1.U){
          when(io.vcon.round === 1.U){                     //right+narrow+round
            shiftResult1(0) := (src1elem1_N(0) + roundvalu(0)) >> shiftvalu(0)
          }.otherwise{                                     //right+narrow
            shiftResult1(0) := src1elem1_N(0) >> shiftvalu(0)
          }
        }.otherwise{                                       //no narrow
          when(io.vcon.round === 1.U){                     //right+round
            shiftResult1(0) :=  (src1elem1(0) + roundvalu(0)) >> shiftvalu(0)
          }.otherwise{                                     //right
            shiftResult1(0) :=  src1elem1(0) >> shiftvalu(0)
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //Result operation                                      Num=1 esize=64//
  when(io.velem.esize === 64.U) {
    when(io.vcon.accum === 1.U) {
      result1(0) := src2elem1(0) + shiftResult1(0)(63, 0)
    }.otherwise {
      when(io.vcon.insert === 1.U && io.vcon.shiftLr === 0.U) {
        shiftMask1(0) := Fill(64, 1.U) << shiftvalu(0)
        result1(0) := (dstElem1(0) & (~shiftMask1(0)).asUInt) | shiftResult1(0)(63, 0) //shift insert
      }.elsewhen(io.vcon.insert === 1.U && io.vcon.shiftLr === 1.U) {
        shiftMask1(0) := Fill(64, 1.U) >> shiftvalu(0)
        result1(0) := (src2elem1(0) & (~shiftMask1(0)).asUInt) | shiftResult1(0)(63, 0) //shift insert
      }.otherwise {
        when(io.vcon.long === 1.U) {
          result1_long(0) := shiftResult1(0)(127,0)
        }.otherwise {
          when(io.vcon.sat === 1.U) {
            when(io.vcon.dstSign === 1.U) {
              when(shiftResult1(0).asSInt > "h7fffffffffffffff".U(64.W).asSInt) {
                result1(0) := "h7fffffffffffffff".U
                io.sat := 1.U
              }.elsewhen(shiftResult1(0).asSInt < "h8000000000000000".U(64.W).asSInt) {
                result1(0) := "h8000000000000000".U(64.W)
                io.sat := 1.U
              }.otherwise {
                result1(0) := shiftResult1(0)(63, 0)
                io.sat := 0.U
              }
            }.otherwise {
              when(shiftResult1(0) > "hffffffffffffffff".U(64.W)) {
                result1(0) := "hffffffffffffffff".U(64.W)
                io.sat := 1.U
              }.elsewhen(shiftResult1(0) < "h0000000000000000".U(64.W)) {
                result1(0) := "h0000000000000000".U(64.W)
                io.sat := 1.U
              }.otherwise {
                result1(0) := shiftResult1(0)(63, 0)
                io.sat := 0.U
              }
            }
          }.otherwise {
            result1(0) := shiftResult1(0)(63, 0)
          }
        }
      }
    }
  }


  //---------------------------------------------------------------------=
  //shiftResult operation                                 Num=2 esize=32//

  when(io.velem.esize === 32.U) {
    for(e <- 0 to 1) {
      when((io.vcon.shiftLr ^ shiftReverse(e)) === 0.U) {
        when(io.vcon.round === 1.U) {
          shiftResult2(e) := (Cat(Fill(128, src1elem2(e)(31)), src1elem2(e)) + roundvalu(e)) << shiftvalu(e) //left+round
        }.otherwise {
          shiftResult2(e) := Cat(Fill(128, src1elem2(e)(31)), src1elem2(e)) << shiftvalu(e) //left
        }
      }.otherwise { //(right）
        when(io.vcon.srcSign === 1.U) {
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+srcsign+narrow+round
              shiftResult2(e) := ((Cat(Fill(96, src1elem2_N(e)(63)), src1elem2_N(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign+narrow
              shiftResult2(e) := (Cat(Fill(96, src1elem2_N(e)(63)), src1elem2_N(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }.otherwise {
            when(io.vcon.round === 1.U) { //right+srcsign+round
              shiftResult2(e) := ((Cat(Fill(128, src1elem2(e)(31)), src1elem2(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign
              shiftResult2(e) := (Cat(Fill(128, src1elem2(e)(31)), src1elem2(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }
        }.otherwise { //(no srcsign)
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+narrow+round
              shiftResult2(e) := (src1elem2_N(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right+narrow
              shiftResult2(e) := src1elem2_N(e) >> shiftvalu(e)
            }
          }.otherwise { //no narrow
            when(io.vcon.round === 1.U) { //right+round
              shiftResult2(e) := (src1elem2(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right
              shiftResult2(e) := src1elem2(e) >> shiftvalu(e)
            }
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //Result operation                                      Num=2 esize=32//

  when(io.velem.esize === 32.U) {
    for (e <- 0 to 1) {
      when(io.vcon.accum === 1.U) {
        result2(e) := src2elem2(e) + shiftResult2(e)(31, 0)
      }.otherwise {
        when(io.vcon.insert === 1.U && io.vcon.shiftLr === 0.U) {
          shiftMask2(e) := Fill(32, 1.U) << shiftvalu(e)
          result2(e) := (dstElem2(e) & (~shiftMask2(e)).asUInt) | shiftResult2(e)(31, 0) //shift insert
        }.elsewhen(io.vcon.insert === 1.U && io.vcon.shiftLr === 1.U) {
          shiftMask2(e) := Fill(32, 1.U) >> shiftvalu(e)
          result2(e) := (src2elem2(e) & (~shiftMask2(e)).asUInt) | shiftResult2(e)(31, 0) //shift insert
        }.otherwise {
          when(io.vcon.long === 1.U) {
            result2_long(e) := shiftResult2(e)(64, 0)
          }.otherwise {
            when(io.vcon.sat === 1.U) {
              when(io.vcon.dstSign === 1.U) {
                when(shiftResult2(e).asSInt > "h7fffffff".U(32.W).asSInt) {
                  result2(e) := "h7fffffff".U(32.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult2(0).asSInt < "h80000000".U(32.W).asSInt) {
                  result2(e) := "h10000000".U(32.W)
                  io.sat := 1.U
                }.otherwise {
                  result2(e) := shiftResult2(e)(31, 0)
                  io.sat := 0.U
                }
              }.otherwise {
                when(shiftResult2(e) > "hffffffff".U(32.W)) {
                  result2(e) := "hffffffff".U(32.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult2(e) < "h00000000".U(32.W)) {
                  result2(e) := "h00000000".U(32.W)
                  io.sat := 1.U
                }.otherwise {
                  result2(e) := shiftResult2(e)(31, 0)
                  io.sat := 0.U
                }
              }
            }.otherwise {
              result2(e) := shiftResult2(e)(31, 0)
            }
          }
        }
      }
    }
  }


  //---------------------------------------------------------------------=
  //shiftResult operation                                 Num=4 esize=16//

  when(io.velem.esize === 16.U) {
    for(e <- 0 to 3) {
      when((io.vcon.shiftLr ^ shiftReverse(e)) === 0.U) {
        when(io.vcon.round === 1.U) {
          shiftResult4(e) := (Cat(Fill(128, src1elem4(e)(15)), src1elem4(e)) + roundvalu(e)) << shiftvalu(e) //left+round
        }.otherwise {
          shiftResult4(e) := Cat(Fill(128, src1elem4(e)(15)), src1elem4(e)) << shiftvalu(e) //left
        }
      }.otherwise { //(right）
        when(io.vcon.srcSign === 1.U) {
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+srcsign+narrow+round
              shiftResult4(e) := ((Cat(Fill(112, src1elem4_N(e)(31)), src1elem4_N(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign+narrow
              shiftResult4(e) := (Cat(Fill(112, src1elem4_N(e)(31)), src1elem4_N(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }.otherwise {
            when(io.vcon.round === 1.U) { //right+srcsign+round
              shiftResult4(e) := ((Cat(Fill(128, src1elem4(e)(15)), src1elem4(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign
              shiftResult4(e) := (Cat(Fill(128, src1elem4(e)(15)), src1elem4(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }
        }.otherwise { //(no srcsign)
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+narrow+round
              shiftResult4(e) := (src1elem4_N(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right+narrow
              shiftResult4(e) := src1elem4_N(e) >> shiftvalu(e)
            }
          }.otherwise { //no narrow
            when(io.vcon.round === 1.U) { //right+round
              shiftResult4(e) := (src1elem4(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right
              shiftResult4(e) := src1elem4(e) >> shiftvalu(e)
            }
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //Result operation                                      Num=4 esize=16//
  when(io.velem.esize === 16.U) {
    for (e <- 0 to 3) {
      when(io.vcon.accum === 1.U) {
        result4(e) := src2elem4(e) + shiftResult4(e)(15, 0)
      }.otherwise {
        when(io.vcon.insert === 1.U && io.vcon.shiftLr === 0.U) {
          shiftMask4(e) := Fill(16, 1.U) << shiftvalu(e)
          result4(e) := (dstElem4(e) & (~shiftMask4(e)).asUInt) | shiftResult4(e)(16, 0) //shift insert
        }.elsewhen(io.vcon.insert === 1.U && io.vcon.shiftLr === 1.U) {
          shiftMask4(e) := Fill(16, 1.U) >> shiftvalu(e)
          result4(e) := (src2elem4(e) & (~shiftMask4(e)).asUInt) | shiftResult4(e)(16, 0) //shift insert
        }.otherwise {
          when(io.vcon.long === 1.U) {
            result4_long(e) := shiftResult4(e)(32, 0)
          }.otherwise {
            when(io.vcon.sat === 1.U) {
              when(io.vcon.dstSign === 1.U) {
                when(shiftResult4(e).asSInt > "h7fff".U(16.W).asSInt) {
                  result4(e) := "h7fff".U(16.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult4(0).asSInt < "h8000".U(16.W).asSInt) {
                  result4(e) := "h8000".U(16.W)
                  io.sat := 1.U
                }.otherwise {
                  result4(e) := shiftResult4(e)(15, 0)
                  io.sat := 0.U
                }
              }.otherwise {
                when(shiftResult4(e) > "hffff".U(16.W)) {
                  result4(e) := "hffff".U(16.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult4(e) < "h0000".U(16.W)) {
                  result4(e) := "h0000".U(16.W)
                  io.sat := 1.U
                }.otherwise {
                  result4(e) := shiftResult4(e)(15, 0)
                  io.sat := 0.U
                }
              }
            }.otherwise {
              result4(e) := shiftResult4(e)(15, 0)
            }
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //shiftResult operation                                 Num=8  esize=8//

  when(io.velem.esize === 8.U) {
    for(e <- 0 to 7) {
      when((io.vcon.shiftLr ^ shiftReverse(e)) === 0.U) {
        when(io.vcon.round === 1.U) {
          shiftResult8(e) := (Cat(Fill(128, src1elem8(e)(7)), src1elem8(e)) + roundvalu(e)) << shiftvalu(e) //left+round
        }.otherwise {
          shiftResult8(e) := Cat(Fill(128, src1elem8(e)(7)), src1elem8(e)) << shiftvalu(e) //left
        }
      }.otherwise { //(right）
        when(io.vcon.srcSign === 1.U) {
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+srcsign+narrow+round
              shiftResult8(e) := ((Cat(Fill(120, src1elem8_N(e)(15)), src1elem8_N(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign+narrow
              shiftResult8(e) := (Cat(Fill(120, src1elem8_N(e)(15)), src1elem8_N(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }.otherwise {
            when(io.vcon.round === 1.U) { //right+srcsign+round
              shiftResult8(e) := ((Cat(Fill(128, src1elem8(e)(7)), src1elem8(e)) + roundvalu(e)).asSInt >> shiftvalu(e)).asUInt
            }.otherwise { //right+srcsign
              shiftResult8(e) := (Cat(Fill(128, src1elem8(e)(7)), src1elem8(e)).asSInt >> shiftvalu(e)).asUInt
            }
          }
        }.otherwise { //(no srcsign)
          when(io.vcon.narrow === 1.U) {
            when(io.vcon.round === 1.U) { //right+narrow+round
              shiftResult8(e) := (src1elem8_N(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right+narrow
              shiftResult8(e) := src1elem8_N(e) >> shiftvalu(e)
            }
          }.otherwise { //no narrow
            when(io.vcon.round === 1.U) { //right+round
              shiftResult8(e) := (src1elem8(e) + roundvalu(e)) >> shiftvalu(e)
            }.otherwise { //right
              shiftResult8(e) := src1elem8(e) >> shiftvalu(e)
            }
          }
        }
      }
    }
  }

  //---------------------------------------------------------------------=
  //Result operation                                       Num=8 esize=8//
  when(io.velem.esize === 8.U) {
    for (e <- 0 to 7) {
      when(io.vcon.accum === 1.U) {
        result8(e) := src2elem8(e) + shiftResult8(e)(15, 0)
      }.otherwise {
        when(io.vcon.insert === 1.U && io.vcon.shiftLr === 0.U) {
          shiftMask8(e) := Fill(8, 1.U) << shiftvalu(e)
          result8(e) := (dstElem8(e) & (~shiftMask8(e)).asUInt) | shiftResult8(e)(16, 0) //shift insert
        }.elsewhen(io.vcon.insert === 1.U && io.vcon.shiftLr === 1.U) {
          shiftMask8(e) := Fill(16, 1.U) >> shiftvalu(e)
          result8(e) := (src2elem8(e) & (~shiftMask8(e)).asUInt) | shiftResult8(e)(16, 0) //shift insert
        }.otherwise {
          when(io.vcon.long === 1.U) {
            result8_long(e) := shiftResult8(e)(15, 0)
          }.otherwise {
            when(io.vcon.sat === 1.U) {
              when(io.vcon.dstSign === 1.U) {
                when(shiftResult8(e).asSInt > "h7f".U(8.W).asSInt) {
                  result8(e) := "h7f".U(8.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult8(0).asSInt < "h80".U(8.W).asSInt) {
                  result8(e) := "h80".U(8.W)
                  io.sat := 1.U
                }.otherwise {
                  result8(e) := shiftResult8(e)(8, 0)
                  io.sat := 0.U
                }
              }.otherwise {
                when(shiftResult8(e) > "hff".U(8.W)) {
                  result8(e) := "hff".U(8.W)
                  io.sat := 1.U
                }.elsewhen(shiftResult8(e) < "h00".U(8.W)) {
                  result8(e) := "h00".U(8.W)
                  io.sat := 1.U
                }.otherwise {
                  result8(e) := shiftResult8(e)(7, 0)
                  io.sat := 0.U
                }
              }
            }.otherwise {
              result8(e) := shiftResult8(e)(7, 0)
            }
          }
        }
      }
    }
  }















  def Elem[T <: Data](op: UInt, vecNum: Int, esize: Int) = {
    val opBuf = WireInit(0.U.asTypeOf(Vec(vecNum, UInt(esize.W))))
    for (e <- 0 until  vecNum) {
      opBuf(e) := op(esize * e + esize - 1, esize * e)
    }
    opBuf
  }

//  def SetBit[T <: Data](op: Vec[T], bin: Bool, vecNum:Int ,esize:Int) = {
//    val opBuf = WireInit(0.U.asTypeOf(Vec(vecNum, UInt(esize.W))))
//    val setBit =  WireInit(0.U.asTypeOf(Vec(1, UInt(esize.W))))
//    for (e <- 0 to vecNum - 1) {
//      for (i <- esize - 1 to 0){
//        when(opBuf(e)(i) === bin){
//          setBit(e) := i.asUInt
//        }
//      }
//    }
//    setBit
//  }

//    def SetBit64(opBuf: Vec[UInt], bin: Bool, vecNum:Int ,esize:Int) = {
//      val setBit =  WireInit(0.U.asTypeOf(Vec(vecNum, UInt(6.W))))
//      val data_1 = Wire(UInt((esize/2).W))
//      val data_2 = Wire(UInt((esize/4).W))
//      val data_3 = Wire(UInt((esize/8).W))
//      val data_4 = Wire(UInt((esize/16).W))
//      val data_5 = Wire(UInt((esize/32).W))
//      when(bin === 1.U) {
//        for (e <- 0 to vecNum - 1) {
//          setBit(e)(5) := opBuf(e)(esize - 1, esize / 2).orR //63:32
//          data_1 := Mux(setBit(e)(5), opBuf(e)(esize - 1, esize / 2), opBuf(e)(esize / 2 - 1, 0))
//          setBit(e)(4) := data_1(esize / 2 - 1, esize / 4).orR //[31:16]
//          data_2 := Mux(setBit(e)(4), opBuf(e)(esize / 2 - 1, esize / 4), opBuf(e)(esize / 4 - 1, 0))
//          setBit(e)(3) := data_2(esize / 4 - 1, esize / 8).orR //[15:8]
//          data_3 := Mux(setBit(e)(3), opBuf(e)(esize / 4 - 1, esize / 8), opBuf(e)(esize / 8 - 1, 0))
//          setBit(e)(2) := data_3(esize / 8 - 1, esize / 16).orR //[7:4]
//          data_4 := Mux(setBit(e)(2), opBuf(e)(esize / 8 - 1, esize / 16), opBuf(e)(esize / 16 - 1, 0))
//          setBit(e)(1) := data_4(esize / 16 - 1, esize / 32).orR //[3:2]
//          data_5 := Mux(setBit(e)(1), opBuf(e)(esize / 16 - 1, esize / 32), opBuf(e)(esize / 32 - 1, 0))
//          setBit(e)(0) := data_5(esize / 32 - 1) //[3:2]
//        }
//        setBit
//      }
//    }


  def Shift[T <: Data](op1: Vec[T], op2: Vec[T], vecNum: Int, esize: Int) = {
    val opBuf = WireInit(0.U.asTypeOf(Vec(vecNum, UInt(192.W))))
    for (e <- 0 to vecNum - 1) {
      opBuf(e) := op1(e).asUInt << op2(e).asUInt
    }
    opBuf
  }

  def srccol[T <: Data](vecNum: Int, a: UInt) = {
    val srccolBuf = WireInit(0.U.asTypeOf(Vec(vecNum, UInt((64/vecNum).W))))
    for (j <- 0 to vecNum-1) { srccolBuf(j) := a((64/vecNum) * j + (64/vecNum) - 1, (64/vecNum) * j) }
    srccolBuf
  }



}